package com.eastedu.superise.handler.question.handler.completion;

import com.eastedu.common.enums.ContentPart;
import com.eastedu.common.enums.MediaTypeEnum;
import com.eastedu.common.enums.QuestionTypeEnum;
import com.eastedu.common.model.question.Fragment;
import com.eastedu.common.model.question.QuestionItemContent;
import com.eastedu.common.model.question.QuestionMainContent;
import com.eastedu.repository.question.mapper.QuestionBasicInfoMapper;
import com.eastedu.repository.question.mapper.QuestionConverterLogMapper;
import com.eastedu.repository.question.po.QuestionConverterLogPO;
import com.eastedu.superise.handler.question.handler.ContentConverter;
import com.eastedu.superise.handler.question.handler.ContentHandler;
import com.eastedu.superise.handler.question.handler.ContentParser;
import lombok.extern.slf4j.Slf4j;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;

/**
 * The type Completion content converter.
 *
 * @author Administrator
 */
@Slf4j
public class CompletionContentHandler implements ContentHandler {
    private static final Map<ContentPart, ContentParser<ContentSummary>> CONTENT_PARSER_MAP = new ConcurrentHashMap<>(10);
    private static final Map<ContentPart, ContentConverter> CONTENT_CONVERTER_MAP = new ConcurrentHashMap<>(10);
    private final QuestionConverterLogMapper questionConverterLogMapper;
    private final QuestionBasicInfoMapper questionBasicInfoMapper;

    static {
        CONTENT_PARSER_MAP.put(ContentPart.STEM, new StemContentParser());
        CONTENT_PARSER_MAP.put(ContentPart.ANSWER, new AnswerContentParser());

        CONTENT_CONVERTER_MAP.put(ContentPart.STEM, new StemContentConverter());
        CONTENT_CONVERTER_MAP.put(ContentPart.ANSWER, new AnswerContentConverter());
    }

    public CompletionContentHandler(QuestionConverterLogMapper questionConverterLogMapper, QuestionBasicInfoMapper questionBasicInfoMapper) {
        this.questionConverterLogMapper = questionConverterLogMapper;
        this.questionBasicInfoMapper = questionBasicInfoMapper;
    }

    @Override
    public <T extends QuestionMainContent<T>> boolean support(T content, com.eastedu.superise.handler.question.handler.answerparentheses.MatchType matchType) {
        return false;
    }

    @Override
    public <T extends QuestionMainContent<T>> void handle(T content) {
        QuestionTypeEnum questionType = content.getQuestionType();
        if (questionType == QuestionTypeEnum.COMPREHENSIVE) {
            this.handleComprehensiveStem(content, t -> isTraditionalCompletion(content));
            List<T> questions = content.getQuestions();
            for (T question : questions) {
                this.handle(question);
            }
        } else if (questionType == QuestionTypeEnum.COMPLETION) {
            this.handle(content, t -> isTraditionalCompletion(content));
        }
    }

    private static <T extends QuestionMainContent<T>> boolean isTraditionalCompletion(T content) {
        List<QuestionItemContent> stem = content.getStem();
        // 是否是结构化填空题
        boolean structuredCompletion = stem.stream().map(QuestionItemContent::getFragments)
                .flatMap(Collection::stream)
                .map(Fragment::getMediaType)
                .anyMatch(mediaTypeEnum -> mediaTypeEnum == MediaTypeEnum.BLANK || mediaTypeEnum == MediaTypeEnum.LOGICAL_PARAGRAPH);
        return !structuredCompletion;
    }

    @Override
    public <T extends QuestionMainContent<T>> void handle(T content, Predicate<T> predicate) {
        if (predicate.test(content)) {
            List<QuestionItemContent> stem = content.getStem();
            ContentSummary summaryStem = CONTENT_PARSER_MAP.get(ContentPart.STEM).parse(null,stem);
            log.info("==================================");
            log.info("题干 => {}", summaryStem.toString());

            List<QuestionItemContent> answer = content.getAnswer();
            ContentSummary summaryAnswer = CONTENT_PARSER_MAP.get(ContentPart.ANSWER).parse(null,answer);
            log.info("答案 => {}", summaryAnswer.toString());
            log.info("==================================");

            if (!MatchType.IGNORE_ANSWER_ORDER.getPredicate().test(summaryStem, summaryAnswer)) {
                saveConverterLog(content,-1,"不符合转换规则");
                return;
            }
            CONTENT_CONVERTER_MAP.get(ContentPart.STEM).convert(stem);
            CONTENT_CONVERTER_MAP.get(ContentPart.ANSWER).convert(answer);
            saveConverterLog(content,1,"已结构化");
        }
        else {
            saveConverterLog(content,1,"原试题已结构化");
        }
    }

    public <T extends QuestionMainContent<T>> void handleComprehensiveStem(T content, Predicate<T> predicate) {
        if (predicate.test(content)) {
            List<QuestionItemContent> stem = content.getStem();
            ContentSummary summaryStem = CONTENT_PARSER_MAP.get(ContentPart.STEM).parse(null,stem);
            log.info("==================================");
            log.info("综合题题干 => {}", summaryStem.toString());

            if(!MatchType.IGNORE_ANSWER_ORDER.getPredicate().test(summaryStem, null)){
                saveConverterLog(content,-1,"综合题题干不符合转换规则");
                return;
            }
            if (summaryStem.getOrderCount() != content.getQuestions().size()) {
                saveConverterLog(content,-1,"综合题题干的小题和真实的小题不一致");
                return;
            }
            CONTENT_CONVERTER_MAP.get(ContentPart.STEM).convert(stem);
            saveConverterLog(content,1,"综合题题干已结构化");
        }
        else
        {
            saveConverterLog(content,1,"原综合题题干已结构化");
        }
    }

    private void saveConverterLog(QuestionMainContent content, Integer status, String msg) {
        this.questionConverterLogMapper.deleteByQuestionIdAndItemId(content.getQuestionId(), content.getId());
        QuestionConverterLogPO questionConverterLogPO = new QuestionConverterLogPO();
        questionConverterLogPO.setQuestionId(content.getQuestionId());
        questionConverterLogPO.setQuestionName(questionBasicInfoMapper.getQuestionName(content.getQuestionId()));
        questionConverterLogPO.setQuestionItemId(content.getId());
        questionConverterLogPO.setOrders(content.getOrder());
        questionConverterLogPO.setStatus(status);
        questionConverterLogPO.setMsg(msg);
        this.questionConverterLogMapper.insert(questionConverterLogPO);
    }
}
